﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using SimpleAppServer.Core;
using System.Net;
using System.Net.Sockets;

namespace SimpleAppServer.Implement.Socket
{
    /// <summary>
    /// Tcp Session
    /// </summary>
    public class TcpSession:AbstractAppSession
    {
        System.Net.Sockets.Socket m_Socket;
        string m_ToString;

        /// <summary>
        /// 构造函数
        /// </summary>
        /// <param name="token">UserToken</param>
        public TcpSession(SocketAsyncEventArgs token) 
            : base(token)
        {
            m_Socket = token.AcceptSocket;
            m_ToString = m_Socket.RemoteEndPoint.ToString();
        }

        /// <summary>
        /// 发送命令
        /// </summary>
        /// <param name="command">命令</param>
        /// <returns>发送成功或失败</returns>
        public override bool Send(ICommand command)
        {
            try
            {
                byte[] buff = command.GetBytes();
                m_Socket.BeginSend(buff, 0, buff.Length, SocketFlags.None,
                    new AsyncCallback(SendCallback), m_Socket);
            }
            catch (Exception ex)
            {
                logger.Debug(ex);
                return false;
            }
            return true;
        }

        /// <summary>
        /// 异步回调方法
        /// </summary>
        /// <param name="iar">IAsyncResult</param>
        void SendCallback(IAsyncResult iar)
        {
            try
            {
                System.Net.Sockets.Socket sK = (System.Net.Sockets.Socket)iar.AsyncState;
                sK.EndSendTo(iar);
            }
            catch (Exception ex)
            {
                logger.Debug(ex);
            }
        }

        object lock_release = new object();

        bool released = false;

        /// <summary>
        /// 释放Session
        /// </summary>
        public override void Release()
        {
            lock (lock_release)   //防止产生并发
            {
                if (!released)
                {
                    try
                    {
                        m_Socket.Shutdown(SocketShutdown.Both);
                        m_Socket.Close();
                        m_Socket.Dispose();
                    }
                    catch (Exception ex)
                    {
                        logger.Debug(ex);
                    }
                    finally
                    {
                        base.Release();
                    }
                    released = true;
                }
            }
        }

        public override string ToString()
        {
            return m_ToString;
        }
    }
}
